#!/usr/bin/env python
# -*- encoding: utf8 -*-

import sys
import optparse


__author__ = 'fcamel'


class CodeGenerator(object):
    def __init__(self, indent_size=4):
        self._indent = ' ' * indent_size

    def create_class(self, class_name, fields):
        codes = []
        codes += self._create_init(class_name, fields)
        codes.append('')
        codes += self._create_eq(fields)
        codes.append('')
        codes += self._create_str(fields)
        codes.append('')
        codes += self._create_cmp(fields)
        return codes

    def _create_init(self, class_name, fields):
        codes = [
            'class %s(object):' % class_name,
            '%sdef __init__(self, %s):' % (self._indent, ', '.join(fields)),
        ]
        for f in fields:
            codes.append('%sself.%s = %s' % (self._indent * 2, f, f))

        return codes

    def _create_eq(self, fields):
        def create_field_eq(field):
            return 'self.%s == other.%s' % (field, field)

        if not fields:
            raise ValueError('fields is empty.')

        # generate __eq__
        eq = [
            '%sdef __eq__(self, other):' % (self._indent),
            '%sif not isinstance(other, type(self)):' % (self._indent * 2),
            '%sreturn False' % (self._indent * 3),
        ]
        eq.append('%sreturn (%s' % (self._indent * 2, create_field_eq(fields[0])))
        for f in fields[1:]:
            eq.append('%s        and %s' % (self._indent * 2, create_field_eq(f)))
        eq[-1] += ')'
        eq.append('')

        # generate __ne__
        ne = [
            '%sdef __ne__(self, other):' % (self._indent),
            '%sreturn not self == other' % (self._indent * 2),
        ]

        return eq + ne

    def _create_str(self, fields):
        parameters = ', '.join(["%s"] * len(fields))
        values = ', '.join('self.%s' % f for f in fields)
        codes = [
            '%sdef __str__(self):' % (self._indent),
            '%sreturn "%s" %% (%s)' % (self._indent * 2, parameters, values)
        ]

        return codes

    def _create_cmp(self, fields):
        def create_field_cmp(field):
            return 'cmp(self.%s, other.%s)' % (field, field)

        if not fields:
            raise ValueError('fields is empty.')

        cmp_ = [
            '%sdef __cmp__(self, other):' % (self._indent),
            '%sif not isinstance(other, type(self)):' % (self._indent * 2),
            '%sreturn False' % (self._indent * 3),
        ]
        cmp_.append('%sreturn (%s' % (self._indent * 2, create_field_cmp(fields[0])))
        for f in fields[1:]:
            cmp_.append('%s        or %s' % (self._indent * 2, create_field_cmp(f)))
        cmp_[-1] += ')'
        cmp_.append('')

        return cmp_



def main(class_name, fields):
    '''\
    %prog [options] <class-name> <fields>

    Example:
        %prog Color red,green,blue
    '''
    print '\n'.join(CodeGenerator().create_class(class_name, fields))

    return 0


if __name__ == '__main__':
    parser = optparse.OptionParser(usage=main.__doc__)
    options, args = parser.parse_args()

    if len(args) != 2:
        parser.print_help()
        sys.exit(1)

    class_name, fields = args

    sys.exit(main(class_name, map(str.strip, fields.split(','))))
